package net.jgrm.common.db.config;

import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.MybatisXMLLanguageDriver;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import io.seata.rm.datasource.DataSourceProxy;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.JdbcType;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;

/**
 * @author: houyong
 * @date: 2025年09月22日 10:23
 */
@Configuration
@MapperScan(basePackages = "net.jgrm.**.mapper", sqlSessionTemplateRef = "sqlSessionTemplate")
public class SeataMybatisPlusConfig {
    /**
     * 1. 初始化动态数据源（包含master和slave配置）
     */
    @Primary
    @Bean("dynamicDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.dynamic")
    public DataSource dynamicDataSource() {
        return new DynamicRoutingDataSource();
    }

    /**
     * 2. 用Seata的DataSourceProxy代理动态数据源（AT模式核心步骤）
     * 注意：必须代理整个动态数据源，而非单独代理master/slave
     */
    @Bean("dataSourceProxy")
    public DataSourceProxy dataSourceProxy(@Qualifier("dynamicDataSource") DataSource dataSource) {
        return new DataSourceProxy(dataSource);
    }

    /**
     * 3. 配置MyBatis-Plus的SqlSessionFactory，使用Seata代理的数据源
     */
    @Bean("sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSourceProxy") DataSourceProxy dataSourceProxy) throws Exception {
        MybatisSqlSessionFactoryBean factoryBean = new MybatisSqlSessionFactoryBean();
        // 设置Seata代理后的数据源
        factoryBean.setDataSource(dataSourceProxy);

        // MyBatis-Plus配置
        MybatisConfiguration configuration = new MybatisConfiguration();
        configuration.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class);
        configuration.setJdbcTypeForNull(JdbcType.NULL);
        configuration.setMapUnderscoreToCamelCase(true); // 下划线转驼峰
        factoryBean.setConfiguration(configuration);

        // 配置Mapper XML路径
        factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath*:mapper/**/*.xml"));

        return factoryBean.getObject();
    }

    /**
     * 4. 配置SqlSessionTemplate
     */
    @Bean("sqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

//    /**
//     * 5. Seata全局事务扫描器（扫描@GlobalTransactional注解）
//     */
//    @Bean
//    public GlobalTransactionScanner globalTransactionScanner() {
//        // 参数1: applicationId（需与Seata Server配置一致）
//        // 参数2: txServiceGroup（事务组，需与yml配置一致）
//        return new GlobalTransactionScanner("business-service", "my_test_tx_group");
//    }
}
